import { Device } from "@/api/interface/iot";
import { getHistoryDataList } from "@/api/modules/iot/data";
import { getProfile } from "@/api/modules/model/profile";
import SystemImg from "@/assets/images/system/system.png";
import BaseChart from "@/components/Chart/BaseChart.vue";
import { formatSize } from "@/utils/format";
import * as echarts from "echarts";
import { YAXisOption } from "echarts/types/dist/shared";
import { dayjs } from "element-plus";
import { defineComponent } from "vue";
import "./index.scss";
const systemDevice = "ssiot-sysinfo-master";
export default defineComponent({
	props: {},
	emits: [],
	setup() {
		const headerEl = ref();
		const cpuEl = ref();
		const menEl = ref();
		const diskEl = ref();
		const autoRefresh = ref<NodeJS.Timeout>();
		const refresh = async () => {
			await headerEl.value.load();
			await menEl.value.load();
			await cpuEl.value.load();
			await diskEl.value.load();
			autoRefresh.value = setTimeout(() => {
				refresh();
			}, 60 * 1000);
		};
		onMounted(() => {
			refresh();
		});
		onBeforeUnmount(() => {
			if (autoRefresh.value) {
				clearTimeout(autoRefresh.value);
			}
		});
		return () => {
			return (
				<div class="system-monitor-page">
					<Header ref={headerEl} />
					<Chart ref={menEl} title="內存使用" dataKey="mem" />
					<Chart ref={cpuEl} title="CPU使用" dataKey="cpu" />
					<Chart ref={diskEl} title="磁盘使用" dataKey="disk" />
				</div>
			);
		};
	}
});

export const Header = defineComponent({
	setup(props, { expose }) {
		const state = reactive({
			cpu: {
				used: 0,
				arch: "amd",
				info: "0"
			},
			mem: {
				diskTotal: 0,
				diskUsed: 0,
				memUsed: 0,
				memoryTotal: 0
			},
			disk: {
				diskTotal: 0,
				diskUsed: 0
			},
			host: {
				hostname: "NanoPi-R6S",
				kernelArch: "aarch64",
				ip: "127.0.0.1",
				kernelVersion: "5.10.110",
				os: "linux",
				platform: "ubuntu",
				platformFamily: "debian",
				platformVersion: "20.04",
				procs: 40,
				uptime: 27,
				virtualizationRole: "",
				virtualizationSystem: ""
			}
		});

		//更新Nvr中的配置
		const load = async () => {
			let res: any = await getProfile({ idSn: systemDevice });
			let system = res.result?.profile?.props?.system || {};
			let sensor = res.result?.profile?.sensor || {};
			state.cpu = { ...system.cpu, ...sensor.cpu };
			state.disk = { ...system.disk, ...sensor.disk };
			state.mem = { ...system.mem, ...sensor.mem };
			state.host.ip = sensor.net.wan;
			if (!state.host.ip) {
				system.net.interfaces.find((item: any) => {
					let addr = (item.addrs?.[0]?.addr || "") as string;
					let flag = addr.endsWith("/24");
					if (flag) {
						state.host.ip = addr;
					}
					return flag;
				});
			}
		};
		const getSize = (val: number) => {
			let v = formatSize(val);
			return v.size + (v.unit || "");
		};
		expose({ load });
		return () => {
			return (
				<div class="system-basic-status grid grid-cols-4 gap-4">
					<div class="status-item disk flex">
						<div class="icon">
							<img src={SystemImg}></img>
						</div>
						<div>
							<div class="data flex">
								<div class="title">服务器IP：</div>
								<div class="value">{state.host.ip}</div>
							</div>
							<div class="data flex">
								<div class="title">操作系统：</div>
								<div class="value">
									{state.host.platform}
									{`（${state.host.os}）`}
								</div>
							</div>
							<div class="data flex">
								<div class="title">CPU架构：</div>
								<div class="value">{state.host.kernelArch}</div>
							</div>
						</div>
					</div>
					<div class="status-item disk flex">
						<div class="icon">
							<img src={SystemImg}></img>
						</div>
						<div class="data pt-1">
							<div class="title">总磁盘</div>
							<div class="value text-lg font-bold pb-3">{getSize(state.disk.diskTotal)}</div>
						</div>
						<div class="data pt-1">
							<div class="title">已使用</div>
							<div class="value text-lg font-bold pb-3">{(state.disk.diskUsed || 0).toFixed(1) || 0}%</div>
						</div>
					</div>
					<div class="status-item mem flex">
						<div class="icon">
							<img src={SystemImg}></img>
						</div>
						<div class="data pt-1">
							<div class="title">总内存</div>
							<div class="value text-lg font-bold pb-3">{getSize(state.mem.memoryTotal)}</div>
						</div>
						<div class="data pt-1">
							<div class="title">已使用</div>
							<div class="value text-lg font-bold pb-3">{(state.mem.memUsed || 0).toFixed(1) || 0}%</div>
						</div>
					</div>
					<div class="status-item cpu flex">
						<div class="icon">
							<img src={SystemImg}></img>
						</div>
						<div class="data pt-1 overflow" style="width:50%;">
							<div class="title">CPU信息</div>
							<div class="value text-lg font-bold pb-3">
								<el-tooltip effect="light" show-after={500} content={state.cpu.info}>
									{state.cpu.info}
								</el-tooltip>
							</div>
						</div>
						<div class="data">
							<div class="title">已使用</div>
							<div class="value text-lg font-bold pb-3">{(state.cpu.used || 0).toFixed(1)}%</div>
						</div>
					</div>
				</div>
			);
		};
	}
});

export const Chart = defineComponent({
	props: {
		title: String,
		dataKey: String
	},
	setup(props, { expose }) {
		const state = reactive({
			dateType: "24h",
			endTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
			startTime: dayjs().add(-24, "h").format("YYYY-MM-DD HH:mm:ss"),
			day: ""
		});
		let optionTemplate: any = {
			animation: false,
			tooltip: {
				trigger: "axis",
				formatter: "{b} <br/> {a}: {c} %",
				axisPointer: {
					type: "shadow"
				}
			},
			toolbox: { show: false },
			legend: {
				show: false,
				type: "scroll",
				orient: "horizontal", //horizontal|vertical
				top: "20px",
				align: "left",
				textStyle: {
					color: "#0070cc",
					fontSize: 14
				}
			},
			grid: {
				top: "30px",
				left: "3%",
				right: "2%",
				bottom: "20px",
				containLabel: true
			},
			xAxis: [
				{
					splitLine: { show: true, lineStyle: { color: "#333" } },
					axisLine: {
						show: true,
						lineStyle: { color: "#f1f1f1" }
					},
					axisLabel: { color: "#f1f1f1", textStyle: { color: "#333" }, formatter: `{value}` },
					type: "category",
					data: []
				}
			],
			yAxis: [
				{
					type: "value",
					splitLine: { show: true, lineStyle: { color: "#333" } },
					axisLine: {
						show: true,
						lineStyle: { color: "#f1f1f1" }
					},
					axisLabel: { color: "#333", formatter: `{value}` }
				}
			] as YAXisOption[],
			series: [] as any[]
		};
		const chart = ref();
		const resize = () => {
			chart.value.resize();
		};
		onMounted(() => {
			chart.value.initChart();
		});
		const load = async () => {
			if (!props.dataKey) {
				let option = JSON.parse(JSON.stringify(optionTemplate));
				option.xAxis[0].data = [];
				chart.value.setChart(option);
				return;
			}
			let res: any = await getHistoryDataList({
				idSn: systemDevice,
				key: props.dataKey,
				keyType: "sensor",
				// pageIndex: 1,
				// pageSize: 1500,
				startTime: state.startTime,
				endTime: state.endTime,
				timeOrder: "asc"
			});
			let dataList = ((res.result?.records || (Array.isArray(res.result) ? res.result : [])) as Device.ResDataInfo[]) || [];
			//根据最大值获取单位
			let max = 0;
			let maxParam: { size: number; unit: string; scale: number } = { size: 0, unit: "b", scale: 1 };
			let option = JSON.parse(JSON.stringify(optionTemplate));
			option.tooltip.formatter = "{b} <br/> {a}: {c} %";
			option.toolbox.show = false;
			// option.tooltip.formatter = `{b} <br/> {a}: {c}${dataList[0].unit}`;
			option.legend.textStyle.color = "#333";
			option.xAxis[0].data = [];
			option.xAxis[0].splitLine.lineStyle.color = "#f1f1f1";
			option.xAxis[0].axisLine.lineStyle.color = "#333";
			option.xAxis[0].axisLabel.textStyle.color = "#333";
			option.yAxis[0].axisLabel.formatter = `{value}%`;
			option.yAxis[0].splitLine.lineStyle.color = "#f1f1f1";
			option.yAxis[0].axisLine.lineStyle.color = "#333";
			option.yAxis[0].axisLabel.color = "#333";
			// option.yAxis[0].axisLabel.formatter = `{value}${dataList[0].unit}`;
			if (props.dataKey == "net") {
				//添加多个y轴
				dataList.forEach(item => {
					let val = Number(item.value?.rx || 0 + item.value?.tx || 0);
					max = max >= val ? max : val;
				});
				maxParam = formatSize(max);
				option.series = [barSeries(`上行流量`), barSeries(`下行流量`)];
				option.yAxis = [getYAxis(maxParam.unit)];
				option.tooltip.formatter = `{b} <br/> {a}: {c} ${maxParam.unit} <br/> {a1}: {c1}${maxParam.unit} `;
			} else if (props.dataKey == "mem") {
				//添加多个y轴
				option.series = [lineSeries("內存使用")];
				dataList.forEach(item => {
					max = max >= item.value?.memoryTotal ? max : item.value?.memoryTotal;
				});
				maxParam = formatSize(max);
			} else if (props.dataKey == "disk") {
				//添加多个y轴
				option.series = [lineSeries("磁盘使用")];
				dataList.forEach(item => {
					max = max >= item.value?.diskTotal ? max : item.value?.diskTotal;
				});
				maxParam = formatSize(max);
			} else if (props.dataKey == "cpu") {
				option.series = [lineSeries("CPU使用")];
			}
			dataList.map((item: any) => {
				let dts = dayjs(item.updateTime);
				let time = dts.isValid() ? dts.format("HH:mm:ss") : item.updateTime;
				option.xAxis[0].data.push(time);
				switch (props.dataKey) {
					case "cpu":
						option.series[0].data.push(item.value?.used ? item.value?.used.toFixed(1) : null);
						break;
					case "disk":
						option.series[0].data.push(item.value?.diskUsed ? item.value?.diskUsed.toFixed(1) : null);
						break;
					case "mem":
						//添加每个轴数据项
						option.series[0].data.push(item.value?.memUsed ? item.value?.memUsed.toFixed(1) : null);
						break;
					case "net":
						//添加每个轴数据项
						option.series[0].itemStyle.color = "#38cb80";
						option.series[0].emphasis = null;
						option.series[0].data.push(item.value?.rx ? (item.value?.rx / maxParam.scale).toFixed(1) : null);

						option.series[1].itemStyle.color = "#1f97ff";
						option.series[1].emphasis = null;
						option.series[1].data.push(item.value?.tx ? (item.value?.tx / maxParam.scale).toFixed(1) : null);
						break;
				}
			});
			chart.value.setChart(option);
		};
		const barSeries = (name: string) => {
			return {
				name: name,
				type: "bar",
				stack: "stack",
				itemStyle: {
					color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
						{ offset: 0, color: "#38cb80" },
						{ offset: 1, color: "#1f97ff" }
					])
				},
				emphasis: {
					//鼠标移动上去高亮
					focus: "series",
					blurScope: "coordinateSystem",
					itemStyle: {
						color: "#38cb80"
					}
				},
				data: []
			};
		};
		const lineSeries = (name: string) => {
			return {
				type: "line",
				smooth: true,
				stack: "stack",
				name: name,
				// 折线图线条颜色
				lineStyle: {
					color: "#1fc4e3",
					width: 2
				},
				showSymbol: false,
				markPoint: { data: undefined },
				//区域图-背景
				areaStyle: {
					opacity: 1,
					color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
						{
							offset: 0, //底部
							color: "#a8e7fe99"
						},
						{
							offset: 1, //顶部
							color: "#a8e7fe10"
						}
					])
				},
				data: []
			};
		};
		const getYAxis = (unit: string): YAXisOption => {
			return {
				splitLine: { show: true, lineStyle: { color: "#fefefe" } },
				type: "value",
				axisLabel: {
					formatter: `{value} ${unit}`,
					fontSize: 13,
					fontWeight: 500,
					color: "#333"
				}
			};
		};
		const changeDateType = () => {
			switch (state.dateType) {
				case "1h":
					state.endTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
					state.startTime = dayjs().add(-1, "h").format("YYYY-MM-DD HH:mm:ss");
					load();
					break;
				case "6h":
					state.endTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
					state.startTime = dayjs().add(-6, "h").format("YYYY-MM-DD HH:mm:ss");
					load();
					break;
				case "24h":
					state.endTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
					state.startTime = dayjs().add(-24, "h").format("YYYY-MM-DD HH:mm:ss");
					load();
					break;
			}
		};
		const changeDay = (type?: string) => {
			if (type) {
				state.day = dayjs(state.day + " 00:00:00")
					.add(type == "add" ? 1 : -1, "d")
					.format("YYYY-MM-DD");
			}
			state.startTime = state.day + " 00:00:00";
			state.endTime = state.day + " 23:59:59";
			load();
		};
		expose({ resize, load });
		return () => {
			return (
				<div class="chart-status mt-4 pt-6 pb-6">
					<div class="title flex justify-between pr-4">
						<span>{props.title}</span>
						<div>
							<el-radio-group v-model={state.dateType} size="default" onChange={changeDateType}>
								<el-radio label="1h">近1小时</el-radio>
								<el-radio label="6h">近6小时</el-radio>
								<el-radio label="24h">近24小时</el-radio>
								<el-radio label="day">其他</el-radio>
							</el-radio-group>
							{state.dateType == "day" ? (
								<div class="absolute z-10 right-6">
									<el-link type="primary" class="mr-2" underline={false} onClick={() => changeDay("sub")}>
										前一天
									</el-link>
									<el-date-picker
										onChange={changeDay}
										value-format="YYYY-MM-DD"
										format="YYYY-MM-DD"
										v-model={state.day}
										type="date"
										placeholder="请选择日期"
										size="default"
									/>
									<el-link type="primary" class="ml-2" underline={false} onClick={() => changeDay("add")}>
										后一天
									</el-link>
								</div>
							) : null}
						</div>
					</div>
					<BaseChart ref={chart} dateType="line" width="100%" height="100%" />
				</div>
			);
		};
	}
});
